package bb.lanxing.nav;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;

import java.util.Iterator;
import java.util.LinkedList;

import bb.lanxing.App;
import bb.lanxing.model.json.RouteStep;

/**
 * 导航管理类
 */
public class NavServiceManager {
    private static NavServiceManager instance;

    private INavigationService navigationService;
    private ServiceConnection mConnection;
    // 已注册的回调列表
    private LinkedList<INavigationServiceCallback> callbacks = new LinkedList<>();

    private NavServiceManager() {
    }

    public static NavServiceManager getInstance() {
        if (instance == null) {
            instance = new NavServiceManager();
        }
        return instance;
    }

    public void launchNav(final long lushuId, boolean playVoice) {
        if (isBind()) {
            try {
                navigationService.startNavigation3(lushuId);
                return;
            } catch (RemoteException e) {
                e.printStackTrace();
                return;
            }
        }
        registerNavigationCallback(navigationStateCallback);
        mConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                if (service == null) {
                    return;
                }
                navigationService = INavigationService.Stub.asInterface(service);
                Iterator it = callbacks.iterator();
                while (it.hasNext()) {
                    try {
                        navigationService.registerCallback((INavigationServiceCallback) it.next());
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
                Runnable startNavigationTask = () -> {
                    try {
                        navigationService.startNavigation3(lushuId);
                    } catch (RemoteException e) {
                        throw new RuntimeException(e);
                    }
                };
                startNavigationTask.run();
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                navigationService = null;
            }
        };
        Intent intent = new Intent(App.getContext(), NavigationService.class);
        intent.putExtra("play_voice", playVoice);
        App.getContext().bindService(intent, mConnection, 1);
    }

    private boolean isBind() {
        return (navigationService == null || mConnection == null) ? false : true;
    }

    public void registerNavigationCallback(INavigationServiceCallback callback) {
        if (!callbacks.contains(callback)) {
            callbacks.add(callback);
        }
        if (isBind()) {
            try {
                navigationService.registerCallback(callback);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    public void unbindService() {
        if (navigationService != null) {
            try {
                Iterator<INavigationServiceCallback> it = callbacks.iterator();
                while (it.hasNext()) {
                    navigationService.unRegisterCallback(it.next());
                }
                navigationService.stopNavigation();
            } catch (RemoteException e) {
                throw new RuntimeException(e);
            }
            App.getContext().unbindService(mConnection);
            navigationService = null;
            mConnection = null;
            unregisterNavigationCallback(navigationStateCallback);
        }
    }

    public void unregisterNavigationCallback(INavigationServiceCallback callback) {
        callbacks.remove(callback);
        if (isBind()) {
            try {
                navigationService.unRegisterCallback(callback);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    public boolean isNavigating() {
        if (navigationService != null) {
            try {
                return navigationService.isNavigating();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    private INavigationServiceCallback.Stub navigationStateCallback = new INavigationServiceCallback.Stub() {
        @Override
        public void onNavFailed(int code) {
        }

        @Override
        public void onNavStart() {
        }

        @Override
        public void onNavUpdate(int type, String msg, double distance) {
        }

        @Override
        public void onNavYaw(RouteStep step) {
        }

        @Override
        public void onYawBack(RouteStep step) {
        }

        @Override
        public void onArrived() {
            unbindService();
        }
    };
}